#include "stdafx.h"
#include "_CoordinateController.h"
#include <limits>
#include <math.h>

_GraphCoordinateController::_GraphCoordinateController(void)
{
    m_MaxX = DBL_MIN;
    m_MinX = DBL_MAX;
    m_MaxY = DBL_MIN;
    m_MinY = DBL_MAX;
    maxTicks = 10;

}


_GraphCoordinateController::~_GraphCoordinateController(void)
{
}

void _GraphCoordinateController::setMinMaxCoordinates(double XMin, double XMax, double YMin, double YMax)
{
    m_MinX = XMin;
    m_MaxX = XMax;
    m_MinY = YMin;
    m_MaxY = YMax;
}

void _GraphCoordinateController::getMinMaxCoordinates(double* XMin, double* XMax, double* YMin, double* YMax)
{
    *XMin = m_MinX;
    *XMax = m_MaxX;
    *YMin = m_MinY;
    *YMax = m_MaxY;
}




/**
 * Instantiates a new instance of the NiceScale class.
 *
 * @param min the minimum data point on the axis
 * @param max the maximum data point on the axis
 */
void _GraphCoordinateController::NiceScale(double min, double max)
{
    minPoint = min;
    maxPoint = max;
    calculate();
}

/**
 * Calculate and update values for tick spacing and nice
 * minimum and maximum data points on the axis.
 */
void _GraphCoordinateController::calculate()
{
    range = niceNum(maxPoint - minPoint, false);
    tickSpacing = niceNum(range / (maxTicks - 1), true);
    niceMin =
        floor(minPoint / tickSpacing) * tickSpacing;
    niceMax =
        ceil(maxPoint / tickSpacing) * tickSpacing;
}

/**
 * Returns a "nice" number approximately equal to range Rounds
 * the number if round = true Takes the ceiling if round = false.
 *
 * @param range the data range
 * @param round whether to round the result
 * @return a "nice" number to be used for the data range
 */
double _GraphCoordinateController::niceNum(double range, bool round)
{
    double exponent; /** exponent of range */
    double fraction; /** fractional part of range */
    double niceFraction; /** nice, rounded fraction */

    exponent = floor(log10(range));
    fraction = range / pow(10, exponent);

    if(round)
    {
        if(fraction < 1.5)
        {
            niceFraction = 1;
        }
        else if(fraction < 3)
        {
            niceFraction = 2;
        }
        else if(fraction < 7)
        {
            niceFraction = 5;
        }
        else
        {
            niceFraction = 10;
        }
    }
    else
    {
        if(fraction <= 1)
        {
            niceFraction = 1;
        }
        else if(fraction <= 2)
        {
            niceFraction = 2;
        }
        else if(fraction <= 5)
        {
            niceFraction = 5;
        }
        else
        {
            niceFraction = 10;
        }
    }

    return niceFraction * pow(10, exponent);
}

/**
 * Sets the minimum and maximum data points for the axis.
 *
 * @param minPoint the minimum data point on the axis
 * @param maxPoint the maximum data point on the axis
 */
void _GraphCoordinateController::setMinMaxPoints(double minPoint1, double maxPoint1)
{
    minPoint = minPoint1;
    maxPoint = maxPoint1;
    calculate();
}

/**
 * Sets maximum number of tick marks we're comfortable with
 *
 * @param maxTicks the maximum number of tick marks for the axis
 */
void _GraphCoordinateController::setMaxTicks(double maxTicks1)
{
    maxTicks = maxTicks1;
    calculate();
}

/**
 * Gets the tick spacing.
 *
 * @return the tick spacing
 */
double _GraphCoordinateController::getTickSpacing()
{
    return tickSpacing;
}

/**
 * Gets the "nice" minimum data point.
 *
 * @return the new minimum data point for the axis scale
 */
double _GraphCoordinateController::getNiceMin()
{
    return niceMin;
}

/**
 * Gets the "nice" maximum data point.
 *
 * @return the new maximum data point for the axis scale
 */
double _GraphCoordinateController::getNiceMax()
{
    return niceMax;
}

bool _GraphCoordinateController::isEqualUpToPrecision(double x1, double x2, unsigned int Precision)
{
    if(_isnan(x1) || _isnan(x2) || x1 < -DBL_MAX || x2 < -DBL_MAX || x1 > DBL_MAX || x2 > DBL_MAX)
    {
        return false;
    }

    if(abs(x1 - x2) > pow(10.0, -(int)Precision))
    {
        return false;
    }
    else
    {
        return true;
    }
}